package leetcode.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by tiang on 2018/7/24.
 * 一个小程序，自己生成测试用例并对比三种算法的结果
 */
public class TestTime {
    /*public static void main(String[] args) {

        CountTime ct = new CountTime();
        for(int i=0;i<100;i++){
            int N = (int)(Math.random()*50)+1;
            int M = (int)(Math.random()*50)+1;
            String[] votes = new String[N];
            for(int j=0;j<votes.length;j++){
                votes[j] = generateString(M);
            }
            System.out.println("****************");
            int zhr = ((Solution)ct.bind(new ZHR())).solve(votes);
            int ztx = ((Solution)ct.bind(new ZTX())).solve(votes);
            int yyc = ((Solution)ct.bind(new YYC())).solve(votes);

            if(zhr != ztx || ztx!=yyc){
                System.out.println("err");
                System.out.println("zhr: "+zhr);
                System.out.println("ztx: "+ztx);
                System.out.println("yyc: "+yyc);
                for(String s : votes){
                    System.out.println(s);
                }
                System.out.println(" =================== ");
            }

            System.out.println("****************");
        }
    }*/
    interface Solution{
        int solve(String[] args);
    }

    static class ZHR implements Solution{

        @Override
        public int solve(String[] strings) {
            int N = strings[0].length();
            int M = strings.length;
            int[] counts = new int[N];
            boolean[] isSelected = new boolean[N];
            for (int i = 0; i < N; i++) {
                isSelected[i] = true;
            }
            int max = 0; // 用来统计每次比较赢的次数
            int min = 0;
            int equal = 0;
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (j != i) {
                        for (int k = 0; k < M; k++) {
                            if (strings[k].charAt(i) < strings[k].charAt(j)) {
                                max++;
                            } else if (strings[k].charAt(i) == strings[k].charAt(j)) {
                                equal++;
                            } else {
                                min++;
                            }
                        }
                        //counts[i] += tmp;

                        if (max <= min) {
                            isSelected[i] = false;
                        }
                        max = 0;
                        min = 0;
                        equal = 0;
                    }
                }
            }
            int index = -1;
            for (int i = 0; i < counts.length; i++) {
                if (isSelected[i]) {
                    index = i;
                }
            }
            return index;
        }
    }

    static class ZTX implements Solution{

        @Override
        public int solve(String[] stars) {
            // 球员数
            int count = stars[0].length();
            Boolean[] isOver = new Boolean[count];
            for(int i=0;i<count;i++){
                if(isOver[i]!=null && !isOver[i])
                    continue;
                boolean isBest = true;
                for(int j=0;j<count;j++){
                    if(i == j)
                        continue;
                    // 如果i比j大，那么j就不可能是最大的
                    if(compare(stars, i, j))
                        isOver[j] = false;
                    else{
                        isBest = false;
                    }
                }
                if(isBest)
                    return i;
            }
            return -1;
        }
        /**
         * 球星A的得票数是否大于球星B
         * @param votes
         * @param posA
         * @param posB
         * @return
         */
        private boolean compare(String[] votes, int posA, int posB) {
            int aCount = 0, bCount = 0;
            for (int j = 0; j < votes.length; j++) {
                if (votes[j].charAt(posA) < votes[j].charAt(posB))
                    aCount++;
                else if (votes[j].charAt(posA) > votes[j].charAt(posB))
                    bCount++;
            }
            return aCount > bCount;
        }
    }

    static class YYC implements Solution{

        @Override
        public int solve(String[] arr) {
            int N = arr[0].length();
            int M = arr.length;
            int[][] counts = new int[N][N];

            for(int i = 0;i<M;i++)
            {
                for(int j = 0;j<N;j++)
                {
                    for(int k = 0;k<N;k++)
                    {

                        if(arr[i].charAt(j)<arr[i].charAt(k))
                        {
                            counts[j][k]++;
                        }
                    }
                }
            }

            //统计票数
            boolean[] isSelected = new boolean[N];

            for(int i = 0;i<N;i++)
            {
                for(int j = 0;j<N;j++)
                {
                    if(counts[i][j]>counts[j][i])
                    {
                        isSelected[j] = true;
                    }
                }
            }

            int res = 0;
            int index = 0;
            for(int i = 0;i<N;i++)
            {
                if(isSelected[i]==false)
                {
                    res++;
                    index = i;
                }
            }

            if(res==1)
            {
                return index;
            }else {
                return -1;
            }
        }
    }

    static class CountTime implements InvocationHandler {

        private Object obj;

        public Object bind(Object aim){
            obj = aim;
            return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    aim.getClass().getInterfaces(), this);
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            long before = System.currentTimeMillis();
            Object result = method.invoke(obj, args);
            long after = System.currentTimeMillis();
            System.out.println(obj.getClass().getName()+": "+(after-before));
            return result;
        }
    }

    private static String generateString(int length){
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<length;i++){
            char c = (char)('a'+(int)(Math.random()*26));
            sb.append(c);
        }
        return sb.toString();
    }
}
